/*
  缓存控制：强制缓存和协商缓存

    1. 浏览器发送请求，获取资源，响应状态码200，返回新资源
      服务器设置响应头：
        强制缓存 cache-control: max-age=3600; expires: GMT时间
          cache-control http 1.1 (优先级更好)
          expires http 1.0

        协商缓存 
          etag 根据文件内容生成标识
          last-modified 文件最近修改时间

    2. 浏览器重新获取资源，在发送请求之前，先判断是否命中强制缓存
        如果命中，直接读取缓存使用，不会再发送请求了，响应状态码 200 （memory cache / disk cache）
        如果没有命中，发送请求给服务器，携带两个请求头：
          if-none-match(就是之前etag的值)
          if-modified-since(就是之前last-modified的值)

        服务器通过解析请求头得到这两个字段，将这两个字段和该文件etag和last-modified进行比较。
          如果都相等，说明文件没有发生变化，服务器返回响应状态码304，
            浏览器得到响应状态码304，就会自动读取缓存使用
          如果不相等，说明文件发生了变化，不能走缓存，服务器需要返回新资源，响应状态码200
            同时会设置新的强制缓存和协商缓存字段
*/

/*
  用户登录，服务器验证用户名密码是否正确，查询用户数据
    对用户数据进行 json web token 加密, 得到 token
    将token以响应体方式响应给浏览器

  下次浏览器发送请求，携带token，服务器以 json web token 解密token。
  得到加密前用户数据，从而识别是哪个用户
*/

const express = require("express");
const fs = require("fs");
const etag = require("etag");

const app = express();

// 返回 index.html
app.get("/", async (req, res) => {
  fs.readFile("./public/index.html", (err, file) => {
    if (err) {
      console.log(err);
      return;
    }

    res.setHeader("content-type", "text/html;charset=utf-8;");
    res.end(file.toString());
  });
});

// /index.js 返回index.js
app.get("/index.js", async (req, res) => {
  console.log("服务器接受到请求 index.js");

  fs.readFile("./public/index.js", (err, file) => {
    if (err) {
      console.log(err);
      return;
    }

    const fileContent = file.toString();

    fs.stat("./public/index.js", (err, stats) => {
      if (err) console.log(err);
      else {
        // 第二次
        const ifNoneMatch = req.headers["if-none-match"];
        const ifModifiedSince = req.headers["if-modified-since"];

        const newEtag = etag(fileContent);
        const lastModified = stats.mtime;

        if (ifNoneMatch && ifModifiedSince) {
          if (
            newEtag === ifNoneMatch &&
            Math.floor(new Date(lastModified).getTime() / 1000) ===
              Math.floor(new Date(ifModifiedSince).getTime() / 1000)
          ) {
            // 说明文件没有发生变化
            console.log("命中了");
            return res.status(304).end();
          }
        }

        // 第一次
        // 设置强制缓存
        res.setHeader("cache-control", "max-age=10");
        // 设置协商缓存
        res.setHeader("etag", newEtag);
        res.setHeader("last-modified", lastModified);

        res.setHeader("content-type", "text/javascript;");
        res.end(fileContent);
      }
    });
  });
});

app.listen(3000, "localhost", (err) => {
  if (err) console.log(err);
  else console.log("服务器启动成功");
});
